/*
 * Quick Reference and FAQ for Chipmunk Basic - MacOS version
 * chipmunk-basic-3.5.2.sit.hqx - 97Apr 
 *
 * Chipmunk Basic is (c) Copyright 1994,1997 Ronald H. Nicholson, Jr.
 * ALL RIGHTS RESERVED
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY OF ANY KIND; not even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Updates to this document may be found on the WWWeb at:
  http://www.nicholson.com/rhn/basic/  

---
Quick Reference for Chipmunk Basic
ported to the MacOS by Ronald H. Nicholson, Jr.	  rhn@nicholson.com 

Supported operators, functions and statements (reserved words):

        + - * / ^ mod  and or xor not  > < >= <= <> =
        sqr() log() exp() sin() cos() tan() atn()  pi
        abs() sgn() int() rnd() peek() val() asc() len()
        mid$() right$() left$() str$() chr$()  lcase$() ucase$()
        goto  if then else endif  gosub return
        for to step next  while wend  select case
        rem  let  dim erase  data read restore   field$()
        input print open for output append as close# load save
        random lof loc get put   
        inkey$  input$ eof()  files  fgetbyte# fseek# fputbyte
        run stop end exit quit cont  renum  new clear
        date$ time$ timer  sound morse say  doevents inputbox
        home cls gotoxy htab vtab pos()  menu
        graphics sprite pset moveto lineto window scrn mouse()
        varptr peek() poke fre push() pop  isarray  mat
        sub call usr  def fn  exec
        type class extends  string integer single double longint
        asin acos sinh cosh tanh log10 floor true false ubound


- The "basic.man" file is included with the distribution.  It
  describes the above functions and statements in more detail.
  
- Line numbers are required for console input.
- The interpreter includes an dumb old fashioned line number based
  editor.  (Enter a line; delete a line; edit one line at a time).
- The variable types are float doubles and strings with a maximum
  length of 254 characters.  Variable names can be up to 31 characters
  in length and are case insensitive.
- Math is done using the built-in double precision IEEE math.
  All trigonometric functions express angles in radians.

---
Some Simple Examples:

  for i=1 to 10 : print i : next i

  c$ = a$ + b$              : rem string concatenation
  a$ = inkey$               : rem inkey$ is non-blocking 
  
  load "sieve.bas"          : rem load TEXT file as a Basic program
                            : rem file names should have .bas extension
  
  open "filename" for output as #1 : print #1, "hello world" : close #1 
  
  graphics 0  : moveto 10,10 : lineto 110,80	: rem draw a line
  
---
Frequently Asked Questions:

Q: Is there more documentation on learning how to program in the
   BASIC language?
A: The language is mostly compatible with books on programming in the
   BASIC language that were published between 1978 and 1988.  Since these
   are mostly out of print, your best bet is to try your local public
   library.
   
   Also, there is a short tutorial on the Chipmunk Basic web page:
        http://www.nicholson.com/rhn/basic/

Q: Why won't this Mumblesoft QuickBasic program run? ...
A: Chipmunk Basic was never intended to be exactly compatible with any
   other commercial BASIC language product.  It does include most of the
   features of ANSI minimal BASIC language definition.  Many BASIC
   programs that are saved as ASCII text files, and that don't use any
   special features of a particular computer OS, can be easily ported
   to Chipmunk Basic.
   
Q: Is there any way to redirect print statements to a line printer?
A: No, there is no way to make this work with current MacOS printer
   drivers. I recommend printing to a file, and then using SimpleText
   to print the file.

   Depending on what kind of printer you have, the command
         call "printText"
   might send the last 66 lines of text from the console window to your
   printer (US letter size only.)

Q: Why can't I load a text file using the "Open" menu?
A: Chipmunk Basic requires that Basic program file names end with a
   ".bas" suffix. However, if you hold down the option key, Chipmunk
   Basic will try to open any TEXT file.

Q: How do I talk to the serial ports using Chipmunk Basic?
A: Chipmunk Basic requires that the Communications ToolBox "Serial Tool"
   be installed in the Extensions folder in your System Folder.  First
   open "COM1:" for input, followed by opening "COM1:" for output.
   The errorstatus$ string variable will return a string you can use
   instead of "COM1:" when you don't want the CTB setup dialog box.
   Try the following snippet:
   
    100 rem   ***  Using the CTB serial ports  ***
    110 on error goto 200
    120 open "COM1:" for input as #3 : altsetup$ = "COM1: "+errorstatus$
    130 open "COM1:" for output as #4
    150 while not mouse(0)
    160   if not eof(3) then i = fgetbyte(3) : print chr$(i);
    170   c$ = inkey$ : if len(c$) > 0 then print #4,c$;
    180 wend
    190 print " closing serial ports" : close #4 : close #3
    200 print errorstatus$ : goto 190

   The command
        CALL "sendbreak", n
   will send a break for n ticks (60ths of a second).
   
   If you can't use the Communications ToolBox Serial Tool for any
   reason,you can try using
        open "COM3: 19200" for input as #3      ' note the COM3:
   instead.  This uses the serial port driver directly (serial port
   only), and isn't as compatible as using the Communications ToolBox.

Q: How do I use sprites?
A: Sprite are little icons that can be moved around in the graphics
   window.  You can use up to 15 sprites, numbered from 1 to 15  Sprites
   will appear in front of any graphics or picts in the graphics window.
   The sprites are in layers; sprite 1 will pass in front of sprite 2
   when they overlap, etc. 
   
   You specify what you want a particular sprite to look like by using
   a resource ID.  For instance a sprite with a resource id of 28 looks
   like the Chipmunk icon, with a resource id of 130 looks like a ball.
   A sprite with with a rsrc id of 0 is invisible.
   
   You may place sprites at an x,y coordinate.  Or you may move them
   around and leave a trail behind them to draw things.  Sprite movement
   commands include { up, down, left, right, forward, turn, turnleft,
   turnright, turnto, penup and pendown }.  To get rid of a sprite,
   simply move them offscreen (e.g. { x,y } = { -1,-1} ).

Q: How do I make my own sprites?
A: I use ResEdit (available from ftp.apple.com).  Just paste the new
   sprite 'ICN#' and 'cicn's into the resource fork of a file.  Then
        open "myresfile.rsrc" for data input
   will use the named resource file for sprite (pict & sound) resources.
   Resource ID's 128-160 are reserved for the Chipmunk Basic interpreter,
   so please use a high resource ID number.  A 'cicn' resource requires
   a 'ICN#' resource with the same ID number.  You can use the same
   method for creating custom PICT and sound resources.  You can also
   paste resources directly into your .bas program text file.
   
Q: Why can't I make my graphics window bigger?
   If you have enough memory in your Mac, try increasing the Preferred
   Memory requirements of Chipmunk Basic using the Finder Get Info dialog.
   Also try decreasing the number of colors in the Monitors Control Panel.

Q: Can you send me a list of different peeks and pokes?
A: Peeks and pokes don't have much use on current Mac Systems.  If you
   want to live dangerously, you might want to get a copy of SysEqu.h or
   LoMem.h from an old C or 68K assembly language programming package;
   but don't expect anything you do to be compatible with the latest
   MacOS System software.

Q: Is there a compiler for Chipmunk Basic?
A: No, however there are several commercial Basic compilers on the market
   (Staz FutureBasic, True Basic, VIP Basic, Oracle Power Objects ...)
   and rumors of major new support for the BASIC language on the Mac
   coming next year (1997 maybe ?,  Kenobi ??, Denali ??? ... ).
   
Q: Why isn't this cool command that I found documented.
A: Any undocumented command is fair game to change in the next version.
   Use at your own risk: Hey, even some of the documented commands change!

Q: (not really a question) The documentation s*cks...  uh, stinks.
A: I'm crazy enough to have found that tinkering with and enhancing
   Chipmunk Basic has been enjoyable use of some spare time.  If you
   are enlightened enough to enjoy writing quality documentation, please
   feel free to contribute your efforts.

Q: What is the history of Chipmunk Basic?
A: In March 1990, p2c, a pascal to c translator, was posted to the usenet
   newsgroup "comp.source.misc" by David Gillespie.  One of the test
   input files was "basic.p".  I used the output c file to learn about
   language interpreters and then ported the resulting Basic interpreter
   to a Mac 512KE and then to a PowerMac 7100.  Chipmunk Basic for
   the PowerMac was posted to Info-Mac on March 15th, 1994, the day
   after the first PowerMacintosh was available for sale to the public.

---
Additional Chipmunk Basic Macintosh specific commands and functions:

- Mac Graphics
  * note: all graphics commands in version 3.x are experimental & beta test *

        GRAPHICS 0                          	:' show graphics window
        graphics -1                        	:' hide graphics window
        graphics WINDOW x, y, width, height	:' graphics window setup
                                :' (x,y) location, width and height
        graphics WINDOW width, height	        :' adjust the size

        graphics MOVETO  x,y	        :' Move pen To x,y
        graphics LINETO  x,y	        :' draw Line To x,y
        
        graphics moveto 10,20 : graphics lineto 30,50	:' example
                        :' that draws a line from (10,20) to (30,50)

        graphics CIRCLE  x	        :' circle of diameter x
                        :' previous MOVETO x,y s ets center location
        graphics OVAL    x,y        	:' oval  x wide by y high

        graphics RECT  x1,y1, x2,y2        	:' FrameRect
        graphics FILLRECT  x1,y1, x2,y2,pat#	:' PaintRect
        graphics FILLRECT  x1,y1, x2,y2,-1	:' EraseRect
        graphics OVAL  x1,y1, x2,y2	        :' FrameOval
        graphics FILLOVAL  x1,y1, x2,y2,pat#	:' PaintOval
        graphics PENSETUP  xsize, ysize [, mode, pat# ] :' modes 8-15
                :' modes - 8 patCopy, 9 patOr, 10 patXor, 11 patBic
                :' pat# - 1 is black, 4 is 50% dots, 12 is bricks, etc.

        graphics COLOR  r,g,b	        :' red green blue 0-100%
        graphics COLOR 100,0,0	        :' changes new color to red
        graphics COLOR  0,0,0	        :' use default black

        graphics pset x,y	                :' plot 1 point at x,y
        graphics TRIANGLE x1,y1,x2,y2,x3,y3 {,r,g,b}  :' draw triangle
        graphics PICT   x,y,n	        :' draw 'pict' resource# n

        graphics DRAWTEXT  a$	        :' DrawText
                :' use MOVETO x,y  to position text lower left corner
        graphics TEXTSETUP f, s, m	:' set up text font, size, mode
        graphics textsetup macfunction("GetFNum","monaco"), 24, 0
                :' modes : 0 srcCopy, 1 srcOr, 2 srcXor, 3 srcBic

        graphics (-38)	            :' get graphics window max width
        graphics (-39)	            :' get graphics window max height
        graphics (-34)	            :' get graphics window pixel depth

        SPRITE	n  x, y, id	    :' sprite n @ x,y using ICN# id
                                    :' n from 1 to 15, 1 frontmost
                                    :' ICN# 128 - 141 included with app
                                    :' cicn requires ICN# with same id.
        sprite	n  UP    x	    :' sprite #n move up x pixels
        sprite  n  DOWN  x	    :'   also returns new sprite y coord
        sprite  n  LEFT  x	    :' move LEFT (not turn as in Logo!)
        sprite  n  RIGHT   x
        sprite	n  TURN    d	    :' turn counter-clockwise d degrees
        sprite	n  TURNRIGHT d	    :' turn clockwise d degrees
        sprite	n  TURNLEFT  d
        sprite	n  TURNTO    d	    :' turn to d degrees from x axis
        sprite	n  FORWARD x	    :' move forward x pixels
        sprite	n  PENUP
        sprite	n  PENDOWN
        sprite	n  COLLISION	    :' returns 1st sprite# in contact
        sprite  id  on  x,y	    :' paste a fixed sprite image @(x,y)

        graphics WINDOW -1,-1, x,y, 2	:' scroll graphics background

        ' Too small a "Preferred Size" (as set from Finder Get Info window)
        ' may limit the maximum graphics window size.

        call "savepicture", fname$
                        :' saves graphics window to a PICT file
                        :' use graphics window command to set size
        graphics PICT x,y,"filename.PICT"
                        :' draws graphics from PICT file at (x,y)

        graphics refreshtime 5	:' approx. 5/60ths second refresh rate
        graphics 0		:' refresh graphics window now
        		:' for control of graphics animation update rate
        
- Mac Sound commands

        morse "CQ DE N6YWU",16,40,13,700        :' play morse code
                :' MORSE string, dot_wpm, volume, letter_wpm, freq
  
        say "hello world"            :'  *requires* the Speech Manager
        say "faster", 196, 44, 1    :'  string, rate, pitch, voice#
        say        	:' reads the last 12 lines of the console window
        x  = macfunction("numSpeakers")	:' the number of voices
        v$ = macfunction("getSpeaker")	:' get the voices name

        sound 440, 0.5, 30	:' freq, secs_duration, vol(0-100)
        sound 0, 8192	        :' play snd resource #8192
        sound -1, a(0),11100    :' play 1 sec. of samples from array a()
        sound -2, midi_voice, midi_key, velocity, secs_dur [,channel]
                :' play Quicktime midi synth, requires Quicktime 2.0
        call "record", a(0), n  :' records n samples of sound into a()

- Mac User interface functions and commands
        
        cls	                : rem clears console & graphics windows
        gotoxy 5,10 : print "here" : rem move text cursor (0,0 origin)
        x = pos(0)	        : rem text cursor horizontal location
        y = pos(-1)	        : rem vertical text cursor location

        a$ = inputbox("prompt", "title", "default", 0)
                :' gets string input using default dialog
        a$ = inputbox("prompt", "title", "default", id)
                :' if id > 1024 this will use a custom DLOG #id
                :'    with item 1 = OK, item 2 = cancel
                :'    prompt replaces 1st static text item
                :'    default replaces 1st edit text item
                
        call "bigfont"	        :' toggles BIGFONT console output status
        call "hideMenuBar"	:' hides menubar. graphics -1 to restore.
        call "wintitle", t$	:' just sets the graphics window title

        mouse(0)        ' returns 1 if the mouse button is down
        mouse(1)        ' x coordinate in current window
        mouse(2)        ' y coordinate in current window
        mouse(3)        ' last x click location (set to -1 after read)
        mouse(4)        ' last y click location (set to -1 after read)
                :' mouse() must follow a graphics command
                :'   to get a location in the graphics window.

        graphics BUTTON title$,x,y,w,h,key_code
                        :' draw a standard button at (x,y) size (w,h)
                        :' will input chr$(key_code) when pressed
        graphics BUTTON title$,x,y,w,h,e$
                        :' button will exec(e$) when pressed
        graphics BUTTON "",x,y,w,h,e$	:' transparent button
        graphics BUTTON "",x,y,id,e$,-4	:' cicn or ICN# id button
        graphics BUTTON "",-1	        :' remove all buttons & sliders

        menu 4, title$, itemlist$, eventlist$	         :' setup menu
        menu 4, "myMenu", "item1;item2", "foo1();foo2()" :' example
                :' sets up the 4th menu (only 4th menu is implemented.)
                :' calls your subroutines foo1() & foo2() on menu select.
                :' subroutines must be previously defined.
                :' see Apple documentation for menu options
        menu 4, ""        :' removes your menu
        doevents()        :' poll for button and menu events

- Additional Mac specific functions and commands:

        open "SFGetFile" for input as #2    :' "SFPutFile" for output
        open "COM1:" for input as #1	    :'  uses CTB Serial Tool
        open "COM3: 9600" for input as #3   :'  uses serial driver
                        :' ** the above file names are case sensitive **
        open f$ for data input as #4	:' data file, no cr-lf translation
        open f$ for data input	    :' use file for resources, picts, etc.
        a$ = field$("aa bb cc", 2," ")	:' returns "bb", (awk fields)

        call "bigfont"	        :' Toggle the BIGFONT console output mode
        call "NoLineNums",1	:' turns off line numbers in list & save
        call "wait", n	                :' waits for n seconds
        call "printText"  :' sends last ~66 console lines to printer

        call "putPref","512",7	:' increase scrollback buffer to 512
                :' you will need to increase the preferred memory size
                :' by 1K for every +10 lines above 256
        call "sendbreak",t  :' serial port break for t ticks (open 1st)
        call varptr(a%(0))	:' calls 68k code located in array a%
                                :' 68k code works even on PPC
        call -151        :' drops into MacsBug (must be installed !!!)
        call "beep", i  :' calls BCMD resource "beep" with 1 *long param
        reply$ = macfunction("Gestalt","cput")  :' system gestalt info
        x = macfunction("keydown", 0x3a)         :' test option key
        s$ = macfunction("getclipstr")	        :' get clipboard text
        call "putstr2clip", s$	        :' put clip if in foreground

        vref = macfunction("lastVRefNum")
        par  = macfunction("lastParID")
                :' gets vRefNum & ParID of the last SFGetFile
                :' or the current dropped program (System 7 only)
        vref = macfunction("prefVRefNum")
        par  = macfunction("prefParID")	:' preferences folder
        files vref, par	                :' sets the default dir
        files dirname$, dummy$	        :' also sets default dir

        call "launch", appname$         :' launch an app in local dir
        call "setfiletype", fname$, "TEXT"        :' set ftype

        macfunction("rsrcload",fname$, rtype$, id, i%(0), sizelim, 2)
        	:' loads rsrc data into an integer array & returns size
        macfunction("rsrcsave",filename$, restype$, res_id, i%(0), size)
        	:' saves the contents of an integer array as a resource

        fre	:' returns available heap memory.
                :' If this gets much below 32K, you should increase the
                :' Preferred size using Finder Get Info & restart Basic.

- Sending AppleScripts and AppleEvents

        call "doscript", appname$, script$	:' send a DoScript AE
        macfunction("doscript", app$, script$)	:' gets result from AE
        call "doscript", app_sig$, text$, ae_class$, ae_id$
                        :' sends appleEvent with text$ as directObject
        call "doscript","MOSS", url$, "GURL", "GURL"
                        :' sends a get URL event to Netscape(tm)

        call "applescript", script$  :' compiles and executes a script.
                        :' script$ can be a single string or a lengthy
                        :' (blank terminated) string array.
                        :' ** requires AppleScript extension **

- A few oddball commands included in version 3.4.x just for fun:

        call "fft_polar", real(0), amp(0), phase(0) , size :' fft
        call "fft_inv",   amp(0), phase(0), real(0) , size :' inverse
                                :' the fft size must a power of 2 : 2^n
        call "math$", "mul$", r$, "1234567890", "9876543210"
            :' 200+ digit string math (add$, sub$, mul$, div$, mod$)

- AppleScript scripting.  Try this script from a script editor:
        tell application "chipbasic" to DoScript "eval ( 5 * 7 )"
        tell application "chipbasic" to DoScript "eval date$"
            :' eval will return a string result to the script editor.
        tell application "chipbasic" to DoScript "print 22 * 7"
        tell application "chipbasic" to DoScript "say 'hello'"
            :' Tells Chipmunk Basic to executes a statement.
      
- A few experimental commands that only work in the 68K Mac version:
        ipaddr = macfunction("dnr2num", domain_name$)
        call "fetchHTTP", ipaddr, httpcmd$, filename$
            :' MacTCP HTTP file transfer, saves to local file
            :' example command:
            :' httpcmd$ = "GET /index.html HTTP/1.0"+chr$(10)+chr$(10)
        :' Strip out the CFRG resource from if you want to make a 
        :'  fat version of cbas into a 68K (unaccelerated) version.

- ICN#, cicn, PICT & BCMD resources may be stored the resource fork of
        any file, not just the "mumble.bas" program file.  Use:
        open "foo.rsrc" for data input : rem with no "as" token,
           :' this makes the file "foo.rsrc" the current resource file

- bigfont options are stored in the Prefs file (edit w/ BBEdit or equiv.)
- safesave feature is enabled by STR# rsrc 140,1
- maximum graphics window size is also stored in the Prefs file.
        if memory is limited the max size is automatically decreased.

---
Editing extensions:

- For users of the test editor BBEdit Lite 3.5, I've included an BBEdit
  extension.  Drop it into the BBEdit Extensions folder.  You can now edit
  your program using BBEdit, and, with a BBEit menu selection, send it to
  Chipmunk Basic to be load and run.
  
  Bug:  The program text must be longer than 32 characters for the
  BBEdit "run contents" command to work.

---
Other notes or Bugs:

- Programs without line numbers can be loaded from a file; however
    sequential line numbers will be added.  The target of a GOTO can
    be a label followed by a colon. e.g.
        foo: print x : x=x-1 : if x>0 then goto foo:
- To save to file without line numbers, try:
	save filename$,"NLN"        : rem - Don't use "goto <number>".
- Other reserved words (don't use these!) :
        msgbox  do loop until break  function
        method private public local   dialog memstat()
        draw play  bload bsave min max
        each redim resume  static  option degrees radians
        eqv imp key is each set width swap
- For the old high precedence NOT operator, enter: #cbas#non_ansi_not

- All input works like the LINE INPUT statement of other Basic versions.
- Line numbers above 999999999 will not list.

---
Important Chipmunk Basic Language changes:
  3.3.7:  type & class vars now require "dim ... as new ..." syntax.
  3.4.7:  lowered NOT operator precedence to match ANSI standard.
          ON-GOTO no longer checks bounds.

Recent Bug fixes:
  3.3.2: fixed sprite turn direction bug
  3.3.5: fixed integer rounding
  3.3.7: fixed assignment to variable "this" in object methods fixed
  3.4.0: fixed default voice in say, input eof bug, pref file bug
  3.4.2: fixed hex$() of negative numbers
  3.4.4: fixed public private default
  3.4.5: fixed moveto & button clear
  3.4.7: fixed fixed nesting of if-then-else
  3.4.8: fixed nesting of select-case
  3.5.1: fixed bbxt junk after end.
         fixed some print using bugs, increased input line to 254 chars.
  3.5.2: added backup on save, fixed 68K stdio EOLN.
  
Please send bug reports to  rhn@nicholson.com

---
Thanks to:
 - Dave Gillespie for writing the original Pascal version of this Basic;
 - Dave Betz for ideas from the original XLisp 1.6 Mac port;
 - many folks from Apple DTS, Metrowerks, c.s.m.p, etc.;
 - John Norstad for making available the Newswatcher TCP source code;
 - Jim Stout for making available "Jim's CDEFs" with source code;
 - Rich Seigal for making BBEdit Lite extendable;
 - Thomas Ferrell for contributing a tutorial for the web page;
 - the many people who who have sent me polite detailed bug reports.
 
---
A  sample program:

--- cut here ---
1 rem "sieve.bas" , a prime number sieve benchmark
2 t = timer
3 dim f(8194)
4 for i = 0 to 8191 : f(i) = 1 : next i
5 s = 8191
6 for i = 0 to s
7   if f(i) = 0 then goto 11
8   p = i+i+3
9   for k = i+p to s step p : f(k) = 0 : next k
10   c = c+1
11 next i
12 print c;" primes found in ";
13 t = timer-t
14 print t;" seconds"
15 end
--- cut here ---
*/
